﻿using System;
using System.Collections;
using System.Threading;
using System.Messaging;
using TRPOP.CMS.Model;
using TRPOP.CMS.Business;
using Newtonsoft.Json;
using TRPOP.Common;
using System.Text;
/*
 * 
 *  MultiThreadPub 类操作说明：
 *  单独的线程来发布页面，这个线程一直监控着任务表，每次读取第一个未执行的任务 
 *  如果没有未执行的任务，那么线程就不再一直等待，不做任何操作，等待系统回收
 *  如果有未执行的任务，那么就循环读取第一个未执行的任务，执行完成后 接着执行下个未完成的任务
 *  
 *   
 */
namespace TRPOP.CMS.Publish
{
    /// <summary>
    /// 多线程发布页面
    /// </summary>
    public class MultiThreadPub
    {
        //线程sleep几毫秒后继续执行, 如果大于0，则sleep，如果小于等于0，则不sleep
        private const int millisecondsTimeout = 100;

        //是否正在执行任务
        public static bool IsRunning = false;

        //激活线程
        public void ActivateThread()
        {
            if (IsRunning == false)
            {
                PubTaskInfo oTop1PubTaskInfo = PubTaskDAL.GetTopMustExecInfo();
                if (oTop1PubTaskInfo != null)
                {
                    RunTask(oTop1PubTaskInfo);
                }
            }
        }

        //执行一个任务,并保存任务状态
        private void ExecuteOneTask(PubTaskInfo oTop1PubTaskInfo, NodeManage mNodeManage)
        {
            try
            {
                PubOnePage(oTop1PubTaskInfo, mNodeManage);
            }
            catch (Exception ex)
            {
                oTop1PubTaskInfo.intTaskStatus = (int)(PubTaskKeys.TaskStatusType.IsProgrameError);
                oTop1PubTaskInfo.nvcContentIDs = ex.Message;
            }
            finally
            {
                PubTaskDAL.Save(oTop1PubTaskInfo);
            }
        }


        //根据任务实体执行任务的详细代码,供ExecuteOneTask调用
        //代码中用到了 Thread.Sleep(0);是为了释放线程所占的cpu资源
        private void PubOnePage(PubTaskInfo oTop1PubTaskInfo, NodeManage mNodeManage)
        {
            //保存当前操作用户的ID
            Thread.SetData(Thread.GetNamedDataSlot("CurrentUserID"), oTop1PubTaskInfo.intAdminID);
            string strNodeids = oTop1PubTaskInfo.intNodeID.ToString();//操作的结点
            string strContentids = oTop1PubTaskInfo.nvcContentIDs;//所有操作的内容ids
            string strAcType = oTop1PubTaskInfo.nvcActiontype;//操作类型
            string strExtras = oTop1PubTaskInfo.nvcContentIDs;//Extras的IDs
            int intIndex = oTop1PubTaskInfo.intIndexPage;//indexPage
            int intcountNum = oTop1PubTaskInfo.intCountNum;//countNum
            int intNodeid = 0;
            NodeInfo oNodeInfo = null;
            int.TryParse(strNodeids, out intNodeid);
            oNodeInfo = mNodeManage.GetInfoById(intNodeid);
            if (oNodeInfo == null)
                oNodeInfo = new NodeInfo();
            bool ExecBln = true;
            switch (strAcType)
            {
                case "node":
                    if (strNodeids.IsEmpty() || strNodeids.Trim().ToLower() == "0")
                    {
                        ExecBln = true;
                    }
                    else
                    {
                        ExecBln = Publish.PublishHtml.PubNode(strNodeids, intIndex, 1);
                        if (intcountNum > 1 && ExecBln)
                        {
                            for (int i = 1; i <= intcountNum - 1; i++)
                            {
                                if (Publish.PublishHtml.PubNode(strNodeids, i + intIndex, 1) == false)
                                    break;
                            }
                        }
                    }
                    break;
                case "content":
                    if (strContentids.IsEmpty() || strContentids.Trim().ToLower() == "0")
                    {
                        ExecBln = true;
                    }
                    else
                    {
                        if (strContentids.Contains(","))//内容分开发布，这样可以避免占用很大的cpu资源
                        {
                            int inttemp = 0;
                            foreach (string strTemp in strContentids.Split(','))
                            {
                                inttemp = 0;
                                if (int.TryParse(strTemp, out inttemp) && inttemp > 0)
                                {
                                    Publish.PublishHtml.PubContent(inttemp.ToString());
                                    //Thread.Sleep(0);
                                }
                            }
                            ExecBln = true;
                        }
                        else
                        {
                            ExecBln = Publish.PublishHtml.PubContent(strContentids);
                        }
                    }
                    break;
                case "Extra":
                    if (strExtras.IsEmpty() || strExtras.Trim().ToLower() == "0")
                    {
                        ExecBln = true;
                    }
                    else
                    {
                        ExecBln = Publish.PublishHtml.PubExtra(strExtras, intIndex, 1);
                        if (intcountNum > 1 && ExecBln)
                        {
                            for (int i = 1; i <= intcountNum - 1; i++)
                            {
                                if (Publish.PublishHtml.PubExtra(strExtras, i + intIndex, 1) == false)
                                    break;
                            }
                        }
                    }
                    break;
                default:
                    ExecBln = false;
                    break;
            }
            if (ExecBln)
                oTop1PubTaskInfo.intTaskStatus = (int)(PubTaskKeys.TaskStatusType.IsExecuteSuccess);
            else
                oTop1PubTaskInfo.intTaskStatus = (int)(PubTaskKeys.TaskStatusType.IsExecuteError);
        }

        /*
         *   不论采用哪种方案，入口函数始终是  RunTask(PubTaskInfo oInfo)
         */   

        #region 单线程发布页面
        //   单线程发布页面:         只有一个线程开启，此线程执行发布页面的工作
        /*

        //是否正在执行任务
        private static bool SingleThread_IsThreadRunning = false;
        //线程锁
        private static readonly object SingleThread_lockObj = new object();
        /// <summary>
        /// 新增一个发布任务，并执行开启线程执行发布任务
        /// </summary>
        /// <param name="oInfo"></param>
        public  void RunTask(PubTaskInfo oInfo)
        {
            if (SingleThread_IsThreadRunning == false)
            {
                lock (SingleThread_lockObj)
                {
                    if (SingleThread_IsThreadRunning == false)
                    {
                        Thread thread = new Thread(this.SingleThread_ExecAllTask);
                        thread.Start();
                        SingleThread_IsThreadRunning = true;
                        IsRunning = true;
                    }
                }
            }
        }
        // 执行发布任务
        private  void SingleThread_ExecAllTask()
        {
            PubTaskInfo oTop1PubTaskInfo = PubTaskDAL.GetTopMustExecInfo();
            NodeManage mNodeManage = new NodeManage();
            do
            {
                if (oTop1PubTaskInfo != null)
                {
                    ExecuteOneTask(oTop1PubTaskInfo, mNodeManage);
                }
                if (millisecondsTimeout > 0)
                {
                    Thread.Sleep(millisecondsTimeout);
                }
                oTop1PubTaskInfo = PubTaskDAL.GetTopMustExecInfo();
            }
            while (oTop1PubTaskInfo != null);
            try
            {
                Thread.CurrentThread.Abort();
            }
            catch
            {

            }
            finally
            {
                //删除过期的任务
                PubTaskDAL.DeleteTask1HoursBefore();
                //当没有需要执行的任务的时候,执行以下代码
                SingleThread_IsThreadRunning = false;
                IsRunning = false;
            }
        }
         
        */
        #endregion

        #region  一个用户对应一个线程
        // 一个用户对应一个线程: 当用户发布页面时，会检测是否有该用户的线程，如果没有的话，则开启新的线程，发布这个用户的页面，否则，不做任何操作
        /* 
        //线程锁
        private static readonly object OneUser1Thread_lockObj = new object();
        //用户ID的Array
        private static ArrayList OneUser1Thread_ArrayUser = new ArrayList();
        /// <summary>
        /// 新增一个发布任务，并执行开启线程执行发布任务
        /// </summary>
        /// <param name="oInfo"></param>
        public void RunTask(PubTaskInfo oInfo)
        {
            if (!OneUser1Thread_ArrayUser.Contains(oInfo.intAdminID))
            {
                lock (OneUser1Thread_lockObj)
                {
                    if (!OneUser1Thread_ArrayUser.Contains(oInfo.intAdminID))
                    {
                        OneUser1Thread_ArrayUser.Add(oInfo.intAdminID);
                        Thread thread = new Thread(new ParameterizedThreadStart(this.ExecAllTask));
                        thread.Start(oInfo.intAdminID);
                        IsRunning = true;
                    }
                }
            }
        }
        //执行发布任务
        private void ExecAllTask(object intAdminID)
        {
            PubTaskInfo oTop1PubTaskInfo = PubTaskDAL.GetTopMustExecInfo(int.Parse(intAdminID.ToString()));
            NodeManage mNodeManage = new NodeManage();
            do
            {
                if (oTop1PubTaskInfo == null)
                    continue;
                ExecuteOneTask(oTop1PubTaskInfo, mNodeManage);
                if (millisecondsTimeout > 0)
                {
                    Thread.Sleep(millisecondsTimeout);
                }
                oTop1PubTaskInfo = PubTaskDAL.GetTopMustExecInfo(int.Parse(intAdminID.ToString()));
            }
            while (oTop1PubTaskInfo != null);
            try
            {
                Thread.CurrentThread.Abort();
            }
            catch
            {

            }
            finally
            {
                lock (OneUser1Thread_lockObj)
                {
                    OneUser1Thread_ArrayUser.Remove(intAdminID);
                    if (OneUser1Thread_ArrayUser.Count == 0)
                        IsRunning = false;
                }
                PubTaskDAL.DeleteTask1HoursBefore();
            }
        }
        */
        #endregion

        #region  多线程发布
        //  多个线程执行发布任务，不论哪个用户添加的任务，这几个线程都是在执行发布任务，如果没有发布任务，则线程自动停止。
        //  当新增新的发布任务时，如果当前有可以执行的线程，则开启新的线程，执行发布任务
        //一共可运行的线程数量
        private const int MutiThread_DefineTotalCount = 2;
        //线程锁
        private static readonly object MutiThread_lockObj = new object();
        //当前运行的线程总数
        private static int MutiThread_CurrentCount = 0;
        //保存当前执行的任务id，以|隔开
        private static StringBuilder strBuild = new StringBuilder(200);
        /// <summary>
        /// 新增一个发布任务，并执行开启线程执行发布任务
        /// </summary>
        /// <param name="oInfo"></param>
        public void RunTask(PubTaskInfo oInfo)
        {
            string strTempFlag = "|" + oInfo.intPubTaskId + "|";
            //如果当前没有执行这个任务, 并且当前执行的线程小于规定的可执行的总线程
            if (!strBuild.ToString().Contains(strTempFlag) && MutiThread_CurrentCount < MutiThread_DefineTotalCount)
            {
                lock (MutiThread_lockObj)
                {
                    if (!strBuild.ToString().Contains(strTempFlag) && MutiThread_CurrentCount < MutiThread_DefineTotalCount)
                    {
                        Thread thread = new Thread(this.MutiThread_ExecAllTask);
                        thread.Start();
                        IsRunning = true;
                        MutiThread_CurrentCount++;
                    }
                }
            }
        }
        // 执行发布任务
        private void MutiThread_ExecAllTask()
        {
            PubTaskInfo oTop1PubTaskInfo = PubTaskDAL.GetTopMustExecInfo();
            NodeManage mNodeManage = new NodeManage();
            do
            {
                #region 执行某个发布任务
                if (oTop1PubTaskInfo != null && !strBuild.ToString().Contains("|" + oTop1PubTaskInfo.intPubTaskId + "|"))
                {
                    ExecuteOneTask(oTop1PubTaskInfo, mNodeManage);
                    strBuild.Replace("|" + oTop1PubTaskInfo.intPubTaskId + "|", "");
                }
                #endregion
                if (millisecondsTimeout > 0)
                {
                    Thread.Sleep(millisecondsTimeout);
                }
                oTop1PubTaskInfo = PubTaskDAL.GetTopMustExecInfo();
            }
            while (oTop1PubTaskInfo != null);
            try
            {
                Thread.CurrentThread.Abort();
            }
            catch
            {

            }
            finally
            {
                //删除过期的任务
                PubTaskDAL.DeletePastTask();
                //当没有需要执行的任务的时候,执行以下代码
                if (MutiThread_CurrentCount > 0)
                {
                    lock (MutiThread_lockObj)
                    {
                        if (MutiThread_CurrentCount > 0)
                        {
                            MutiThread_CurrentCount--;
                        }
                    }
                }
                else
                {
                    lock (MutiThread_lockObj)
                    {
                        if (MutiThread_CurrentCount <= 0)
                        {
                            IsRunning = false;
                        }
                    }
                }
            }
        }

        #endregion
    }
}
